home *** CD-ROM | disk | FTP | other *** search
- #include <stdio.h>
- #include <string.h>
-
- /*
- ---------------------------------------------------------------------------
- TC_XMEM.C - This is a short program to demonstrate how to use the XMEM
- function in Turbo C. All it does is take one string, move it
- to extended memory at location 100000 (1 megabyte boundary),
- then takes it from extended memory and places it into a second
- array. As you can see, we do initialize o_message to the test
- string and n_message to nothing, but we never touch any of them
- again until it is time to show you the results of XMEM.
-
- In essence, this is a heck of a roundabout way to do a strcpy,
- but the possibilities for applications are boundless.
-
- There are four statements here that will generate four non-
- portability warnings, particularly between memory models, but
- we ignore them since we are only trying to show how XMEM works.
- ---------------------------------------------------------------------------
- */
-
- unsigned s_seg, /* Source data segment */
- d_seg, /* Destination segment */
- s_off, /* Source offset */
- d_off, /* Destination offset */
- size; /* Size, in bytes, of data to transfer */
-
- char *s_meg, /* Megabyte boundary of source, 0 to 15 */
- *d_meg; /* Megabyte boundary of destination, 0 to 15 also */
-
- /* Note that one of the two must have a value of 0 since XMEM transfers */
- /* to/from DOS memory, which is below the 1 megabyte boundary */
-
- int result; /* Holds return code from XMEM */
- int CPU; /* Holds type of CPU currently in machine */
- char VDISK_ON; /* Used to tell us if VDISK is alive */
- unsigned long temp2; /* For our own temp purposes also */
-
- char o_message[36]; /* The source area */
- char n_message[36]; /* The destination (target) area */
- char v_save[36]; /* Temp area to save VDISK boot sec */
-
- /* This is the structure that defines the IBM PC-DOS VDISK boot record */
- /* structure. Here is where we get the info to determine if VDISK is */
- /* is installed and how much of extended memory has it already */
- /* allocated to itself. */
-
- typedef struct {
- char jump_code[3]; /* Boot jump code, all 0's */
- char vendor_id[8]; /* Should contain "VDISKx.x" */
- int bytes_per_sector; /* Bytes per sector in ram disk */
- char sectors_per_cluster; /* Sectors per cluster */
- int reserved_sectors; /* Number of reserved sectors */
- char fat_copies; /* Number of FAT copies */
- int dir_entries; /* Number of root dir entries */
- int num_sectors; /* Total number of sectors */
- char media; /* Media descriptor bytes */
- int sectors_per_fat; /* Sectors occupied by one FAT */
- int sectors_per_track; /* Number of sectors per track */
- int heads; /* Number of heads */
- int hidden; /* Number of hidden sectors */
- int em_start; /* Starting loc of 1st free area... */
- /* ...in extended memory/1024 */
- } vdisk_boot_sec;
-
- vdisk_boot_sec BOOT_SEC;
-
- /* IOADDRESS is used to set port to read/write to */
- /* IODATA is used to read/write data once port is selected */
-
- #define IOADDRESS 0x070
- #define IODATA 0x071
-
- /* These variables hold the CMOS extended memory size information */
-
- int EXT_LO, EXT_HI, EXT_TOTAL;
-
- main()
- {
-
- printf("TC_XMEM: Demonstration of the XMEM assembly language\n");
- printf(" routine to mode data to/from extended memory\n");
-
- CPU = CPUID();
- if ((CPU != 286) && (CPU != 386))
- {
- result = 99;
- error_handle();
- }
-
- printf("TC_XMEM: CPU is 80%d.\n",CPU);
-
- /* Let's see how much extended memory we have, if any... */
-
- EXT_LO = portpeek(0x017);
- EXT_HI = portpeek(0x018);
- EXT_TOTAL = ((EXT_HI << 8) + EXT_LO);
-
- if (EXT_TOTAL > 0)
- {
- printf("TC_XMEM: %dK extended memory installed.\n",EXT_TOTAL);
- printf(" Total memory is %dK.\n",(EXT_TOTAL+1024));
- printf(" This includes DOS, video, reserved and extended memory.\n");
- }
- else
- {
- result = 7;
- error_handle();
- }
-
- /* At this point we do a quick check of the first few bytes of extended */
- /* ram to find out if VDISK is already in place. We cannot check for any */
- /* other ram disks because VDISK is the only one that we have documentation */
- /* for and it's the only one (that we know) that tells us where in extended */
- /* memory the ram disk buffers end. */
-
- /* Source is address 100000, location of boot record of VDISK if installed */
-
- s_seg = s_off = 0;
- s_meg = 1;
-
- /* Destination maps into the vdisk_boot_sec structure to decode the meaning */
- /* of life in the VDISK fast lane... */
-
- d_seg = _DS; /* small/tiny memory model only! */
- d_off = &BOOT_SEC.jump_code[0];
- d_meg = 0;
-
- /* Size is size of boot record in bytes, 32 bytes */
-
- size = 32;
-
- /* All set, bring it down and let's take a look at it! */
-
- result = XMEM(s_seg,s_off,s_meg,d_seg,d_off,d_meg,size);
-
- /* Check for error */
-
- if (result > 0) error_handle();
-
- /* No errors. First, let's see if we have a VDISK */
-
-
- VDISK_ON = strstr(BOOT_SEC.vendor_id,"VDISK");
- if (VDISK_ON != 0)
- {
- printf("TC_XMEM: VDISK is installed.\n");
- printf(" VDISK buffer(s) end at %uK\n",BOOT_SEC.em_start);
- if (BOOT_SEC.em_start >= (EXT_TOTAL+1024))
- {
- printf(" VDISK has allocated all extended memory.\n");
- }
- printf(" Saving VDISK Boot Record.\n");
- d_off = &v_save;
- size = 36;
- result = XMEM(s_seg,s_off,s_meg,d_seg,d_off,d_meg,size);
- }
-
-
- strcpy(o_message,"This is a test of the XMEM function.");
- strcpy(n_message,"\0x00");
-
- printf("TC_XMEM: Source and target initialized.\n");
- printf(" Source area contains:\n");
- printf(" [ %s ]\n",o_message);
- printf(" Target area contains:\n");
- printf(" [ %s ]\n",n_message);
-
- /* Since we are working with the small memory model here, we know that the */
- /* source string data is located in segment _DATA, which is grouped under */
- /* DGROUP, whose value is in the DS: segment. For other memory models, you */
- /* must decode any "far" pointers to determine what segment the source */
- /* is located in. */
-
- s_seg = _DS; /* tiny/small memory model only! */
-
- /* source offset is the address of o_message (tiny,small memory models) */
-
- s_off = &o_message;
-
- /* Source is in DOS memory */
-
- s_meg = 0;
-
- /* Destination setup, move string to address 10000:0 */
-
- d_seg = d_off = 0;
- d_meg = 1;
-
- /* Transferring 36 bytes, length of string */
-
- size = 36;
-
- /* Setup completed, call XMEM and send the string to extended memory */
- /* storage. */
-
- result = XMEM(s_seg,s_off,s_meg,d_seg,d_off,d_meg,size);
-
- /* Check to see if any errors detected. */
-
- if (result > 0) error_handle();
-
- /* No errors, say so */
-
- printf("TC_XMEM: Move from low to high mem successful.\n");
-
- /* Ok, now we set source to 100000, where data is now stored, and target */
- /* to the location where we have allocated space for the string */
-
- s_seg = s_off = 0;
- s_meg = 1;
- d_seg = _DS; /* tiny/small memory model only! */
- d_off = &n_message;
- d_meg = 0;
-
- /* Heads up, data coming down! */
-
- result = XMEM(s_seg,s_off,s_meg,d_seg,d_off,d_meg,size);
-
- /* Check to see if we have any errors */
-
- if (result > 0) error_handle();
-
- /* Everything seems ok, say so, then print both strings to prove that */
- /* we actually copied the data */
-
- printf("TC_XMEM: Move from high to low mem successful.\n");
- printf(" Source area contains:\n");
- printf(" [ %s ]\n",o_message);
- printf(" Target area contains:\n");
- printf(" [ %s ]\n",n_message);
-
- /* If VDISK is installed we now have to restore the boot sector in */
- /* extended RAM so as to keep everything in working condition... */
-
- if (VDISK_ON != 0)
- {
- printf(" Restoring VDISK Boot Sector.\n");
- s_seg = _DS;
- s_meg = 0;
- s_off = &v_save;
- d_seg = d_off = 0;
- d_meg = 1;
- size = 36;
- result = XMEM(s_seg,s_off,s_meg,d_seg,d_off,d_meg,size);
- if (result > 0) error_handle();
- }
-
- printf("TC_XMEM: Done.\n");
-
- exit(0);
- }
-
- /* This is our error handler */
-
- error_handle()
- {
- printf("\aERROR : ");
- switch (result)
- {
- case 1 : printf("Memory parity error.\n");
- break;
- case 2 : printf("Exception interrupt error.\n");
- break;
- case 3 : printf("8042 slave CPU error.\n");
- break;
- case 5 : printf("Programming error, bounds.\n");
- break;
- case 6 : printf("Not enough extended memory available.\n");
- break;
- case 7 : printf("No extended memory installed.\n");
- break;
- case 99: printf("Program needs 80286 or 80386 CPU.\n");
- break;
- default: printf("Unknown error.\n");
- }
- exit(result);
- }
-
- /* ------------------------------------------------------------------- */
- /* This routine returns the current value in CMOS ram for the location */
- /* passed to the function in the variable "location". */
- /* ------------------------------------------------------------------- */
-
- portpeek(location)
- unsigned int location;
- {
- outportb(IOADDRESS,location);
- return(inportb(IODATA));
- }
-